package myCobra

import (
	"fmt"
	"github.com/spf13/pflag"
	"os"
	"strings"
)

var (

)

type Command struct {
	Use string

	Short string
	Long string
	Run func(cmd *Command, args []string)

	// commands is the list of commands supported by this program.
	commands []*Command
	nextcommand *Command // sub command at run time

	// parent is a parent command for this command.
	parent *Command

	args []string
	pflags *pflag.FlagSet
}


/**
 * @api {get} /myCobra.go/PersistentFlags() PersistentFlags()
 * @apiName PersistentFlags()
 * @apiGroup Flags
 * @apiDescription 用来添加Flag
 */
func (c *Command) PersistentFlags() *pflag.FlagSet{
	if c.pflags == nil{
		c.pflags = pflag.NewFlagSet(c.Name(),pflag.ContinueOnError)
	}
	return c.pflags
}

/**
 * @api {get} /myCobra.go/Name() Name()
 * @apiName Name()
 * @apiGroup Flags
 * @apiDescription 返回Use的第一个词
 */
func (c *Command) Name() string{
	name := c.Use
	i := strings.Index(name," ")
	if i>=0{
		name = name[:i]
	}
	return name
}

/**
 * @api {get} /myCobra.go/AddCommand() AddCommand()
 * @apiName addCommand()
 * @apiGroup Command
 * @apiDescription 用来在cmd的中添加命令
 */
func (c *Command) AddCommand(sub *Command) {
	for _, v := range c.commands {
		if v == sub {
			return
		}
	}
	c.commands = append(c.commands, sub)
	sub.parent = c
}

func (c *Command) Execute() error {
	if  c == nil {
		return fmt.Errorf("Called Execute() on a nil Command")
	}
	if  c .parent == nil { // root Command
		ParseArgs(c, os.Args[1:])
	}
	c.execute()
	return nil
}

func (c *Command) execute() {
	if c.nextcommand == nil {
		for _, v := range c.args {
			if v == "-h" || v == "--help" {
				c.PrintHelp()
				return
			}
		}
		c.Run(c, c.args)
		return
	}
	c.nextcommand.execute()
}

/**
 * @api {get} /myCobra/paraArgs() paraArgs() 
 * @apiName paraArgs() 
 * @apiGroup Args
 * @apiParam {Command} c 当前命令
 * @apiParam {[]string} args 传入的命令字符串
 */
func ParseArgs(c *Command,args []string){
	//当args的长度小于0的时候，终止递归
	if len(args) < 1{
		return
	}
	for _,v :=range c.commands{
		if v.Use == args[0]{
			c.args = args[:1]
			c.nextcommand = v
			//继续存储下一个命令的子命令
			ParseArgs(v,args[1:])
			return
		}
	}
	c.args = args
	c.PersistentFlags().Parse(c.args)
}


/**
 * @api {get} /myCobra.go/PrintHelp() PrintHelp()
 * @apiName PrintHelp()
 * @apiGroup Flags
 * @apiDescription 输出帮助信息
 */
func (c *Command) PrintHelp(){
	fmt.Printf("%s\n\n",c.Long)

	fmt.Printf("Usage:\n")
	fmt.Printf("\t%s [flags]\n",c.Name())
	if  len(c.commands) > 0 {
		fmt.Printf("\t%s [command]\n\n",c.Name())
		fmt.Printf("Available Commands:\n")
		for _,v := range c.commands{
			fmt.Printf("\t%-10s%s\n",v.Name(),v.Short)
		}
	}

	fmt.Printf("\nFlags:\n")

	c.PersistentFlags().VisitAll(func(flag *pflag.Flag){
		fmt.Printf("\t-%1s, --%-6s %-12s%s (default \"%s\")\n", flag.Shorthand, flag.Name,  flag.Value.Type(), flag.Usage, flag.DefValue)
	})

	fmt.Printf("\t-%1s, --%-19s%s%s\n", "h", "help", "help for ", c.Name())
	fmt.Println()
	if len(c.commands) > 0 {
		fmt.Printf("Use \"%s [command] --help\" for more information about a command.\n", c.Name())
	}
}
